/* eslint-disable no-param-reassign */
import { decamelizeKeys } from 'humps';
import produce from 'immer';
import uniqBy from 'lodash/uniqBy';
import invariant from 'tiny-invariant';
const logicList = ['and', 'or', 'not'];

function filterOne(node, banList) {
  const toRemoveIndex = [];
  if (node.filters) {
    for (let i = 0; i < node.filters.length; i++) {
      const current = node.filters[i];
      if (current.type === 'tag' && banList.includes(current.group_id)) {
        toRemoveIndex.push(i);
      }
      if (['or', 'and', 'not'].includes(current?.type)) {
        filterOne(current, banList);
      }
    }
    node.filters = node.filters.filter(
      (_, index) => !toRemoveIndex.includes(index),
    );
  }
}

// 将后端的 filter 转成 ui 可理解的 filter
const remoteFilterToFilterData = (data, copyLabels) => {
  data = JSON.parse(data);
  const selectedGroup = copyLabels.filters?.[0].filters?.[0].filters
    ?.map(({ groupId }) => groupId)
    .filter(Boolean);

  const typeList = [];
  let cur = data;
  while (logicList.includes(cur.type)) {
    typeList.push(cur.type);
    cur = cur.filters[0];
  }

  invariant(
    typeList.length >= 2,
    'remoteFilterToFilterData error, fitlerdata may be not as deep as expect',
  );
  invariant(
    typeList[typeList.length - 1] === 'and' &&
      typeList[typeList.length - 2] === 'or',
    'remoteFilterToFilterData error,  the logic is not struct is not right as expect',
  );
  let curRoot = data;
  const sectionList = [];
  for (let d = 0; d < typeList.length - 2; d++) {
    sectionList.unshift({
      filters: curRoot.filters[1].filters,
      type: curRoot.type,
    });
    curRoot = curRoot.filters[0];
  }

  const remoteFilters = [curRoot, ...sectionList];

  // 从 filters 中过滤掉已经和选中冲突的

  const resultFilter = produce(remoteFilters, (draft) => {
    filterOne({ type: 'and', filters: draft }, selectedGroup);
    draft[0].filters[0].filters.push(
      ...decamelizeKeys(copyLabels.filters[0].filters[0].filters),
    );
    draft[0].filters[0].filters = uniqBy(
      draft[0].filters[0].filters,
      ({ group_id, custom_id }) => group_id || custom_id,
    );
  });

  return {
    type: 'and',
    filters: resultFilter,
  };
};

export default remoteFilterToFilterData;
